home *** CD-ROM | disk | FTP | other *** search
/ The Best of MacTutor - S…e Code for Volumes 1 to 5 / The Best of MacTutor - Source Code for Volume 1-5 (Wayzata Technology)(6031)(1990).bin / Source Code / #39 (Dec 88) / Twindow / TWindows.c < prev    next >
Text File  |  1988-04-29  |  65KB  |  2,266 lines

  1. /*
  2.  *    TWindows.c
  3.  *
  4.  *    C source of an extended Window Manager that supports tool  windows;
  5.  *    these are windows that always float on top, for palettes and tools.
  6.  *
  7.  *    Written in MPW C 2.0
  8.  *
  9.  *        Copyright Thomas Fruin 1988
  10.  *        All rights reserved.
  11.  *
  12.  *        fruin@hlerul5.BITNET            University of Leiden
  13.  *        thomas@uvabick.UUCP                University of Amsterdam
  14.  *        dibs@well.UUCP
  15.  *        hol0066.AppleLink
  16.  *        2:508/15.FidoNet                The Netherlands
  17.  */
  18.  
  19.  
  20. /*
  21.  *    T O O L B O X   I N C L U D E S
  22.  *
  23.  *    Header files for the Toolbox data types and functions
  24.  *    used in this source file.
  25.  */
  26.  
  27. #include <Types.h>
  28. #include <Memory.h>
  29. #include <Quickdraw.h>
  30. #include <Events.h>
  31. #include <Windows.h>
  32. #include <ToolUtils.h>
  33. #include <OSUtils.h>
  34. #include <Resources.h>
  35.  
  36.  
  37. /*
  38.  *    T O O L B O X   D E F I N I T I O N S
  39.  *
  40.  *    Definitions of low memory global variables:
  41.  *
  42.  *     o    GrayRgn is a handle to the current desktop region, a region
  43.  *        encompassing the  complete desktop space  ( possibly spread
  44.  *        out over more than one screen).  Only needed on the old 64K
  45.  *        ROM Macintosh and the Mac XL,  since there is the new func-
  46.  *        tion GetGrayRgn that also returns this handle.
  47.  *     o    WindowList is a pointer to the very first window.  By  tra-
  48.  *        versing the nextWindow fields in each WindowRecord, you can
  49.  *        access each window in turn.  This global is more than  just
  50.  *        FrontWindow(),  because the function only returns the first
  51.  *        _visible_ window.
  52.  */
  53.  
  54. #define GrayRgn            (*(RgnHandle *)0x9EE)
  55. #define WindowList        (*(WindowPeek *)0x9D6)
  56.  
  57.  
  58. /*
  59.  *    D E F I N I T I O N S
  60.  *
  61.  *    The constants used in this source file.
  62.  */
  63.  
  64.     /* Defines LONGINT, INTEGER, the windowKind constants
  65.        and the externally callable TWindow Manager functions. */
  66.  
  67. #include <TWindows.h>
  68.  
  69.     /* Result codes describing window positions, as
  70.        returned by the function GetWPosition. */
  71.  
  72. #define    alone                0    /* no other windows visible          */
  73. #define    beforeDialog        1    /* it is before the frontmost      */
  74.                                 /* window, which is a dialog      */
  75. #define    beforeSystem        2    /* it is before the frontmost      */
  76.                                 /* window, which is a DA          */
  77. #define    beforeTool            3    /* it is before the frontmost      */
  78.                                 /* window, which is a tool          */
  79. #define    beforeDocument        4    /* it is before the frontmost      */
  80.                                 /* window, which is a document      */
  81. #define    behindFrontSystem    5    /* it is behind the frontmost      */
  82.                                 /* window, which is a DA          */
  83. #define    betweenTools        6    /* it is among the tool windows      */
  84. #define    behindTools            7    /* it is behind all tool windows, */
  85.                                 /* but before document windows      */
  86. #define    behindSystem        8    /* it is behind all tool windows, */
  87.                                 /* and behind a DA                  */
  88. #define    betweenDocuments    9    /* it is behind the frontmost      */
  89.                                 /* document window                  */
  90.  
  91.     /* Miscellaneous */
  92.  
  93. #define    deactivFlag        0        /* modifiers for deactivate event */
  94. #define    noDrag            -32768    /* possible result of DragGrayRgn */
  95. #define    invisible        false    /* when calling NewWindow          */
  96. #define    curVersion        1        /* current version of SysEnvirons */
  97. #define    postponeCalc    true    /* postpone CalcVisBehind call      */
  98. #define    normalCalc        false    /* do normal CalcVisBehind call      */
  99.  
  100.  
  101. /*
  102.  *    T Y P E S
  103.  *
  104.  *    Type definitions of some structures.
  105.  */
  106.  
  107.     /* The WINDData structure matches the structure of a WIND resource
  108.        in a resource file.  It is used to access the various fields of
  109.        the WIND resource after it has been read in from the file. */
  110.  
  111. struct WINDRecord
  112.     {
  113.         Rect        boundsRect;
  114.         INTEGER        procID;
  115.         Boolean        visible;
  116.         char        filler1;
  117.         Boolean        goAwayFlag;
  118.         char        filler2;
  119.         LONGINT        refCon;
  120.         Str255        title;
  121.     };
  122. typedef struct WINDRecord    WINDData;
  123. typedef    struct WINDRecord    *WINDPtr;
  124. typedef    struct WINDRecord    **WINDHandle;
  125.  
  126.     /* The WDEFHeader structure matches the structure of the (optional)
  127.        header of a window definition procedure resource. */
  128.  
  129. struct WDEFRecord
  130.     {
  131.         INTEGER        branch;
  132.         INTEGER        flags;
  133.         LONGINT        type;
  134.         INTEGER        ID;
  135.         INTEGER        version;
  136.     };
  137. typedef struct WDEFRecord    WDEFHeader;
  138. typedef struct WDEFRecord    *WDEFPtr;
  139. typedef struct WDEFRecord    **WDEFHandle;
  140.  
  141.  
  142. /*
  143.  *    G L O B A L S
  144.  *
  145.  *    The TWindow Manager's globals.   ToBeActivated and toBeDeactivated  hold
  146.  *    the next window to be activated and deactivated respectively. FrontTool-
  147.  *    Window, backToolWindow and frontDocWindow are pointers to the  frontmost
  148.  *    visible tool window, the backmost visible tool window, and the frontmost
  149.  *    visible document window.  FirstRgn and secondRgn are region handles that
  150.  *    are used in several places in the TWindow Manager,but are allocated only
  151.  *    once for efficiency.   TheWorld is a standard SysEnvirons data structure
  152.  *    that describes the capabilities of the system we are running on.
  153.  */
  154.  
  155. static WindowPeek    toBeActivated,
  156.                     toBeDeactivated,
  157.                     frontToolWindow,
  158.                     backToolWindow,
  159.                     frontDocWindow;
  160. static RgnHandle    firstRgn,
  161.                     secondRgn;
  162. static SysEnvRec    theWorld;
  163.  
  164.  
  165. /*
  166.  *    T I N I T W I N D O W S
  167.  *
  168.  *    TInitWindows must be called before any other TWindow  Manager  functions
  169.  *    are called. It is used to initialize the global variables.
  170.  *
  171.  *    Note that TInitWindows is no replacement for InitWindows.  It does _not_
  172.  *    call InitWindows; that is up to the calling application.
  173.  *
  174.  *    Parameters:
  175.  *
  176.  *        <none>
  177.  *
  178.  *    Local variables and used functions:
  179.  *
  180.  *        OSErr        err;                result of SysEnvirons call
  181.  *
  182.  *    Global variables and constants:
  183.  *
  184.  *        WindowPeek    frontToolWindow,    frontmost tool window
  185.  *                    backToolWindow,        backmost tool window
  186.  *                    frontDocWindow,        frontmost document window
  187.  *                    toBeActivated,        window that needs activating
  188.  *                    toBeDeactivated;    window that needs deactivating
  189.  *        RgnHandle    firstRgn,            region used for various purposes
  190.  *                    secondRgn;            region used for various purposes
  191.  */
  192.  
  193. void
  194. TInitWindows()
  195. {
  196.     OSErr        err;
  197.  
  198.     frontToolWindow =
  199.     backToolWindow  =
  200.     frontDocWindow  =
  201.     toBeDeactivated =
  202.     toBeActivated   = nil;
  203.     firstRgn  = NewRgn();
  204.     secondRgn = NewRgn();
  205.     err = SysEnvirons( curVersion, &theWorld );
  206. }
  207.  
  208.  
  209. /*
  210.  *    T G E T N E W W I N D O W
  211.  *
  212.  *    TGetNewWindow is a special version of the GetNewWindow call for creating
  213.  *    tool windows and documents windows, as specified by a window template in
  214.  *    a resource file.  If the window template could not be read in  from  the
  215.  *    resource file,   or the window definition function for this window could
  216.  *    not be read into memory, nil is returned.  The window's windowKind field
  217.  *    is set to the value of the windowKind parameter. If you want this window
  218.  *    to behave as a tool window, pass the constant toolKind as windowKind.
  219.  *
  220.  *    TGetNewWindow first calls  GetResource to get the window  template  into
  221.  *    memory.  In then calls NewWindow to create the window, invisible. If the
  222.  *    caller specified a visible window  ( by setting the visible field in the
  223.  *    template to true), the function TShowWindow is called to make it visible
  224.  *    and to update any global variables,post activate events and to make sure
  225.  *    the window appears in its proper plane.
  226.  *
  227.  *    Parameters:
  228.  *
  229.  *      IN:
  230.  *
  231.  *        INTEGER        windowKind;            type of window to create;
  232.  *
  233.  *        The rest of TGetNewWindow's parameters are the same as the
  234.  *        parameters for the standard toolbox function GetNewWindow.
  235.  *
  236.  *      OUT:
  237.  *
  238.  *        WindowPtr    TGetNewWindow();    the new window
  239.  *
  240.  *    Local variables and used functions:
  241.  *
  242.  *        Rect        boundsRect;            NewWindow parameter
  243.  *        Str255        title;                NewWindow parameter
  244.  *        Boolean        visible;            NewWindow parameter
  245.  *        INTEGER        procID;                NewWindow parameter
  246.  *        Boolean        goAwayFlag;            NewWindow parameter
  247.  *        LONGINT        refCon;                NewWindow parameter
  248.  *        WindowPtr    theWindow,            the new window
  249.  *        WINDHandle    theWINDHandle;        handle to window template
  250.  *        WINDPtr        theWINDPtr;            pointer to window template
  251.  *
  252.  *    Constants:
  253.  *
  254.  *        Boolean        invisible;            false, so window is invisible
  255.  */
  256.  
  257. WindowPtr
  258. TGetNewWindow( windowKind, windowID, wStorage, behind )
  259.     INTEGER        windowKind;
  260.     INTEGER        windowID;
  261.     Ptr            wStorage;
  262.     WindowPtr    behind;
  263. {
  264.     Rect        boundsRect;
  265.     Str255        title;
  266.     Boolean        visible;
  267.     INTEGER        procID;
  268.     Boolean        goAwayFlag;
  269.     LONGINT        refCon;
  270.     WindowPtr    theWindow;
  271.     WINDHandle    theWINDHandle;
  272.     WINDPtr        theWINDPtr;
  273.  
  274.         /* Read the window template in from the resource file. */
  275.  
  276.     theWINDHandle = ( WINDHandle )GetResource( 'WIND', windowID );
  277.     if ( theWINDHandle != nil )
  278.     {
  279.             /* Copy the window template values to variables in
  280.                preparation of a NewWindow call. */
  281.  
  282.         theWINDPtr = *theWINDHandle;
  283.         boundsRect = theWINDPtr->boundsRect;
  284.         visible    = theWINDPtr->visible;
  285.         procID     = theWINDPtr->procID;
  286.         goAwayFlag = theWINDPtr->goAwayFlag;
  287.         refCon     = theWINDPtr->refCon;
  288.         if ( theWINDPtr->title.length == 0 )
  289.             title.length = 0;
  290.         else
  291.             BlockMove( &( theWINDPtr->title ), &title,
  292.                        ( Size )theWINDPtr->title.length + 1 );
  293.         p2cstr( &title );
  294.  
  295.             /* Release the used resource.  Create the window, but
  296.                make it invisible. */
  297.  
  298.         ReleaseResource(( Handle )theWINDHandle );
  299.         theWindow = NewWindow( wStorage, &boundsRect, &title, invisible,
  300.                                procID, behind, goAwayFlag, refCon );
  301.         if ( theWindow != nil )
  302.         {
  303.                 /* Set the windowKind field.  If the window is a tool,
  304.                    make sure it is highlighted.  If the user originally
  305.                    specified a visible window in the window template,
  306.                    show it now. */
  307.  
  308.             (( WindowPeek )theWindow )->windowKind = windowKind;
  309.             if ( visible != false )
  310.                 TShowWindow( theWindow );
  311.         }
  312.     }
  313.     else
  314.         theWindow = nil;
  315.     return( theWindow );
  316. }
  317.  
  318. /* End of TGetNewWindow */
  319.  
  320.  
  321. /*
  322.  *    T N E W W I N D O W
  323.  *
  324.  *    TNewWindow is a special version of the NewWindow call for creating  tool
  325.  *    windows and documents windows.  If the window  definition  function  for
  326.  *    this window could not be read into memory, nil is returned. The window's
  327.  *    windowKind field is set to the value of the windowKind parameter. If you
  328.  *    want this window to behave as a tool window,  pass the constant toolKind
  329.  *    as windowKind.
  330.  *
  331.  *    TNewWindow calls NewWindow to create the window, invisible. If a visible
  332.  *    window was specified by the caller,  the  function TShowWindow is called
  333.  *    to make it visible and to  update  any global variables,  post  activate
  334.  *    events and to make sure the window appears only in the plane  it  should
  335.  *    be in.
  336.  *
  337.  *    Parameters:
  338.  *
  339.  *      IN:
  340.  *
  341.  *        INTEGER        windowKind;            type of window to create
  342.  *
  343.  *        The rest of TNewWindow's parameters are the same as the
  344.  *        parameters for the standard toolbox function NewWindow.
  345.  *
  346.  *      OUT:
  347.  *
  348.  *        WindowPtr    TNewWindow();        the new window
  349.  *
  350.  *    Local variables and used functions:
  351.  *
  352.  *        WindowPtr    theWindow;            the new window
  353.  *
  354.  *    Constants:
  355.  *
  356.  *        Boolean        invisible;            false, so window is invisible
  357.  */
  358.  
  359. WindowPtr
  360. TNewWindow( windowKind, wStorage, boundsRect, title,
  361.             visible, procID, behind, goAwayFlag, refCon )
  362.     INTEGER        windowKind;
  363.     Ptr            wStorage;
  364.     Rect        *boundsRect;
  365.     char        *title;
  366.     Boolean        visible;
  367.     INTEGER        procID;
  368.     WindowPtr    behind;
  369.     Boolean        goAwayFlag;
  370.     LONGINT        refCon;
  371. {
  372.     WindowPtr    theWindow;
  373.  
  374.         /* Create the window, invisible. */
  375.  
  376.     theWindow = NewWindow( wStorage, boundsRect, title, invisible,
  377.                            procID, behind, goAwayFlag, refCon );
  378.     if ( theWindow != nil )
  379.     {
  380.             /* Set the windowKind field.  If the window is a tool,
  381.                make sure it is highlighted.  If the user specified
  382.                a visible window, show it now. */
  383.  
  384.         (( WindowPeek )theWindow )->windowKind = windowKind;
  385.         if ( visible != false )
  386.             TShowWindow( theWindow );
  387.     }
  388.     return( theWindow );
  389. }
  390.  
  391. /* End of TNewWindow */
  392.  
  393.  
  394. /*
  395.  *    T C L O S E W I N D O W
  396.  *
  397.  *    TCloseWindow is a replacement for  the standard CloseWindow function
  398.  *    in the toolbox.  It  calls THideWindow first, to make the window in-
  399.  *    visible.  Then it calls CloseWindow to close the window.  Finally it
  400.  *    checks if there is a pending  deactivate  event  for  the window. If
  401.  *    there is,  it removes the deactivate event,  since it is  no  longer
  402.  *    necessary.
  403.  *
  404.  *    Parameters:
  405.  *
  406.  *      IN:
  407.  *
  408.  *        WindowPtr    theWindow;            window to be closed
  409.  *
  410.  *    Global variables:
  411.  *
  412.  *        WindowPtr    toBeDeactivated;    window that needs deactivating
  413.  */
  414.  
  415. void
  416. TCloseWindow( theWindow )
  417.     WindowPtr    theWindow;
  418. {
  419.     THideWindow( theWindow );
  420.     CloseWindow( theWindow );
  421.  
  422.     if ( theWindow == toBeDeactivated )
  423.         toBeDeactivated = nil;
  424. }
  425.  
  426. /* End of TCloseWindow */
  427.  
  428.  
  429. /*
  430.  *    T D I S P O S E W I N D O W
  431.  *
  432.  *    TDisposeWindow is a replacement for the  standard DisposeWindow trap
  433.  *    in the toolbox.  It  calls THideWindow first, to make the window in-
  434.  *    visible. Then it calls DisposeWindow to dispose of the windowrecord.
  435.  *    Finally it checks if there is a pending  deactivate  event  for  the
  436.  *    window.   If there is,  it removes the deactivate event, since it is
  437.  *    no longer necessary.
  438.  *
  439.  *    Parameters:
  440.  *
  441.  *      IN:
  442.  *
  443.  *        WindowPtr    theWindow;            window to be disposed of
  444.  *
  445.  *    Global variables:
  446.  *
  447.  *        WindowPtr    toBeDeactivated;    window that needs deactivating
  448.  */
  449.  
  450. void
  451. TDisposeWindow( theWindow )
  452.     WindowPtr    theWindow;
  453. {
  454.     THideWindow( theWindow );
  455.     DisposeWindow( theWindow );
  456.  
  457.     if ( theWindow == toBeDeactivated )
  458.         toBeDeactivated = nil;
  459. }
  460.  
  461. /* End of TDisposeWindow */
  462.  
  463.  
  464. /*
  465.  *    T S E L E C T W I N D O W
  466.  *
  467.  *    TSelectWindow is a replacement for the Toolbox routine SelectWindow.
  468.  *    It moves the selected document window to the front,  just behind the
  469.  *    the backmost tool window, highlights it, and marks it for activation
  470.  *    for the next TGetNextEvent call. The current frontmost window is un-
  471.  *    highlighted, and is marked for deactivation.   Tool windows can also
  472.  *    be selected when the user clicks them:  they are moved completely to
  473.  *    the front, just like SelectWindow does.
  474.  *
  475.  *    If a desk accessory is in front when  a window is selected,  all the
  476.  *    tool windows and the frontmost document window will be moved on  top
  477.  *    of the desk accessory.
  478.  *
  479.  *    Parameters:
  480.  *
  481.  *      IN:
  482.  *
  483.  *        WindowPtr    theWindow;            window to be selected
  484.  *
  485.  *    Local variables and used functions:
  486.  *
  487.  *        void        BringForward();        brings a window forward behind
  488.  *                                        another
  489.  *        WindowPeek    thePWindow,            WindowPeek version of the window
  490.  *                    theFrontWindow,        frontmost window
  491.  *                    NextVisWindow(),    next visible window in the list
  492.  *                    PrevVisWindow();    previous visible window in the list
  493.  *        INTEGER        theWKind,            windowKind of the theWindow
  494.  *                    frontWKind;            windowKind of the theFrontWindow
  495.  *        Boolean        toolsVisible,        true if tool windows are visible
  496.  *                    BringToolsForward();brings all tool windows in front,
  497.  *                                        when there's a DA on top
  498.  *
  499.  *    Global variables:
  500.  *
  501.  *        WindowPeek    frontToolWindow,    frontmost tool window
  502.  *                    backToolWindow,        backmost tool window
  503.  *                    frontDocWindow,        frontmost document window
  504.  *                    toBeActivated,        window that needs activating
  505.  *                    toBeDeactivated;    window that needs deactivating
  506.  *
  507.  *    Constants:
  508.  *
  509.  *        INTEGER        systemKind,            windowKind value for DAs
  510.  *                    toolKind;            windowKind value for tool windows
  511.  */
  512.  
  513. void
  514. TSelectWindow( theWindow )
  515.     WindowPtr    theWindow;
  516. {
  517.     void        BringForward();
  518.     WindowPeek    thePWindow,
  519.                 theFrontWindow,
  520.                 NextVisWindow(),
  521.                 PrevVisWindow();
  522.     INTEGER        theWKind,
  523.                 frontWKind;
  524.     Boolean        toolsVisible,
  525.                 BringToolsForward();
  526.  
  527.             /* Initialize some variables. */
  528.  
  529.     thePWindow       = ( WindowPeek )theWindow;
  530.     theFrontWindow = ( WindowPeek )FrontWindow();
  531.     theWKind       = TGetWKind( theWindow );
  532.     frontWKind       = TGetWKind(( WindowPtr )theFrontWindow );
  533.  
  534.     if ( theWKind == toolKind )
  535.     {
  536.         if ( frontWKind == systemKind )
  537.         {
  538.                 /* Window is a tool window, with a desk accessory
  539.                    on top.  Select the tool (to unhighlight the
  540.                    DA).  Use BringToolsForward to move the rest of
  541.                    the tools.  Move a possible document window to
  542.                    the front with  BringForward.  Update globals. */
  543.  
  544.             SelectWindow( theWindow );
  545.             (void)BringToolsForward( thePWindow );
  546.             if ( frontDocWindow != nil )
  547.             {
  548.                 frontDocWindow->hilited = true;
  549.                 BringForward( frontDocWindow, backToolWindow,
  550.                               normalCalc );
  551.                 toBeActivated = frontDocWindow;
  552.             }
  553.             frontToolWindow = thePWindow;
  554.         }
  555.         else
  556.         {
  557.                 /* Window is a tool window, and no desk accessory
  558.                    on top.  Find the new backToolWindow if that is
  559.                    necessary, then bring our window to the front.
  560.                    Update our globals. */
  561.  
  562.             if ( thePWindow != frontToolWindow )
  563.             {
  564.                 if ( thePWindow == backToolWindow )
  565.                 {
  566.                     backToolWindow = NextVisWindow( toolKind, thePWindow );
  567.                     if ( backToolWindow == nil )
  568.                         backToolWindow = PrevVisWindow( thePWindow );
  569.                 }
  570.                 BringToFront( theWindow );
  571.                 frontToolWindow = thePWindow;
  572.             }
  573.         }
  574.     }
  575.     else if ( theWKind == userKind )
  576.     {
  577.         if ( frontWKind == systemKind )
  578.         {
  579.                 /* Window is a document window (or a modeless dialog
  580.                    window), with a desk accessory on top.  Use Bring-
  581.                    ToolsForward to move the tools to the front. This
  582.                    unhighlights the desk accessory.  Finish by moving
  583.                    the document window to the front (using SelectWindow
  584.                    if there were no tools to unhighlight the DA). */
  585.  
  586.             toolsVisible = BringToolsForward(( WindowPeek )inFront );
  587.             if ( toolsVisible == false )
  588.                 SelectWindow( theWindow );
  589.             else
  590.             {
  591.                 thePWindow->hilited = true;
  592.                 BringForward( theWindow, backToolWindow, normalCalc );
  593.             }
  594.             toBeActivated  =
  595.             frontDocWindow = thePWindow;
  596.         }
  597.         else
  598.         {
  599.                 /* Window is a document window (or a modeless dialog
  600.                    window), and no desk accessory on top.  If it isn't
  601.                    already the frontmost window, use SelectWindow to
  602.                    bring it to the front if there are no tool windows
  603.                    visible, otherwise use BringForward to move the
  604.                    document window just behind the backToolWindow. */
  605.  
  606.             if ( thePWindow != frontDocWindow )
  607.             {
  608.                 if ( frontToolWindow == nil )
  609.                     SelectWindow( theWindow );
  610.                 else
  611.                 {
  612.                     HiliteWindow(( WindowPtr )frontDocWindow, false );
  613.                     thePWindow->hilited = true;
  614.                     BringForward( thePWindow, backToolWindow,
  615.                                   normalCalc );
  616.                 }
  617.                 toBeDeactivated = frontDocWindow;
  618.                 toBeActivated   =
  619.                 frontDocWindow  = thePWindow;
  620.             }
  621.         }
  622.     }
  623. }
  624.  
  625. /* End of TSelectWindow */
  626.  
  627.  
  628. /*
  629.  *    T H I D E W I N D O W
  630.  *
  631.  *    THideWindow is a replacement for the toolbox routine HideWindow.  It
  632.  *    is used to make a window invisible  ( it has no effect if the window
  633.  *    is already invisible).  If the window is the frontmost document win-
  634.  *    dow and there is a document window behind it, THideWindow will high-
  635.  *    light that window and post an  activate event for it.  If the window
  636.  *    behind it is a desk accessory and there are still  tool  windows  in
  637.  *    front, the desk accessory will be brought in front of the tools.
  638.  *
  639.  *    THideWindow uses GetWPosition to find out the exact position of  the
  640.  *    window with respect to other windows on the desktop.   It then takes
  641.  *    specific action for each type of position, such as moving windows to
  642.  *    an allowed location first, or highlighting windows manually, posting
  643.  *    activate events and updating the global  variables  frontToolWindow,
  644.  *    backToolWindow and frontDocWindow.
  645.  *
  646.  *    Parameters:
  647.  *
  648.  *      IN:
  649.  *
  650.  *        WindowPtr    theWindow;            window to be hidden
  651.  *
  652.  *    Local variables and used functions:
  653.  *
  654.  *        WindowPeek    thePWindow,            WindowPeek version of theWindow
  655.  *                    behindWindow;        window behind theWindow when
  656.  *                                        theWindow is behindTools
  657.  *        INTEGER        theWKind,            the window's windowKind
  658.  *                    thePosition,        the window's relative position
  659.  *                    GetWPosition();        determines window's position
  660.  *        void        HiliteTools();        (Un)highlights all the tools
  661.  *
  662.  *    Global variables:
  663.  *
  664.  *        WindowPeek    frontToolWindow,    frontmost tool window
  665.  *                    backToolWindow,        backmost tool window
  666.  *                    frontDocWindow,        frontmost document window
  667.  *                    toBeActivated,        window that needs activating
  668.  *                    toBeDeactivated;    window that needs deactivating
  669.  *
  670.  *    Constants:
  671.  *
  672.  *        INTEGER        systemKind,            windowKind for DA windows
  673.  *                    toolKind,            windowKind for tool windows
  674.  *                    alone,                no other windows visible
  675.  *                    beforeDialog,        it is before the frontmost window,
  676.  *                                        which is a dialog window
  677.  *                    beforeSystem,        it is before the frontmost window,
  678.  *                                        which is a system window
  679.  *                    beforeTool,            it is before the frontmost window,
  680.  *                                        which is a tool window
  681.  *                    beforeDocument,        it is before the frontmost window,
  682.  *                                        which is a document window
  683.  *                    behindFrontSystem,    it is behind the frontmost window,
  684.  *                                        which is a system window
  685.  *                    betweenTools,        it is among the tool windows
  686.  *                    behindTools,        it is behind all the tool windows
  687.  *                                        but before any document windows
  688.  *                    behindSystem,        it is behind all the tool windows
  689.  *                                        and behind a system window
  690.  *                    betweenDocuments;    it is behind the first document
  691.  *                                        window
  692.  */
  693.  
  694. void
  695. THideWindow( theWindow )
  696.     WindowPtr    theWindow;
  697. {
  698.     WindowPeek    thePWindow,
  699.                 behindWindow;
  700.     INTEGER        theWKind,
  701.                 thePosition,
  702.                 frontWKind,
  703.                 GetWPosition();
  704.     void        HiliteTools();
  705.  
  706.     if ((( WindowPeek )theWindow )->visible != false )
  707.     {
  708.             /* Save some window values, for later unhighlighting
  709.                and deactivating. */
  710.  
  711.         thePWindow  = ( WindowPeek )theWindow;
  712.         theWKind    = TGetWKind( theWindow );
  713.         thePosition = GetWPosition( thePWindow, &frontWKind );
  714.  
  715.             /* Hide the window, and update the desktop
  716.                according to the window's position. */
  717.  
  718.         if ( theWKind == toolKind )
  719.         {
  720.                 /* The window is a tool window. */
  721.  
  722.             switch( thePosition )
  723.             {
  724.                 case alone:
  725.                 case beforeSystem:
  726.                         HideWindow( theWindow );
  727.                         frontToolWindow =
  728.                         backToolWindow  = nil;
  729.                         break;
  730.  
  731.                 case beforeTool:
  732.                         ShowHide( theWindow, false );
  733.                         frontToolWindow = ( WindowPeek )FrontWindow();
  734.                         break;
  735.  
  736.                 case behindFrontSystem:
  737.                         ShowHide( theWindow, false );
  738.                         frontToolWindow =
  739.                             NextVisWindow( toolKind, thePWindow );
  740.                         if ( frontToolWindow == nil )
  741.                             backToolWindow = nil;
  742.                         break;
  743.  
  744.                 case beforeDocument:
  745.                         frontToolWindow =
  746.                         backToolWindow  = nil;
  747.                         ShowHide( theWindow, false );
  748.                         break;
  749.  
  750.                 /* NOTE: no behindTools possible! */
  751.  
  752.                 case betweenTools:
  753.                         ShowHide( theWindow, false );
  754.                         if ( thePWindow == backToolWindow )
  755.                             backToolWindow = PrevVisWindow( thePWindow );
  756.                         break;
  757.             }
  758.         }
  759.         else if ( theWKind == userKind )
  760.         {
  761.                 /* The window is a document window
  762.                    (or a modeless dialog window). */
  763.  
  764.             thePWindow->hilited = false;
  765.  
  766.             switch( thePosition )
  767.             {
  768.                 case alone:
  769.                 case beforeSystem:
  770.                         toBeDeactivated = thePWindow;
  771.                         frontDocWindow  = nil;
  772.  
  773.                 case betweenDocuments:
  774.                         HideWindow( theWindow );
  775.                         break;
  776.  
  777.                 case beforeDocument:
  778.                         HideWindow( theWindow );
  779.                         toBeDeactivated = thePWindow;
  780.                         toBeActivated   =
  781.                         frontDocWindow  = ( WindowPeek )FrontWindow();
  782.                         break;
  783.  
  784.                 case behindFrontSystem:
  785.                         ShowHide( theWindow, false );
  786.                         frontDocWindow =
  787.                             NextVisWindow( userKind, theWindow );
  788.                         break;
  789.  
  790.                 case behindTools:
  791.                         frontDocWindow =
  792.                             NextVisWindow( userKind, theWindow );
  793.                         behindWindow =
  794.                             NextVisWindow( anyKind, theWindow );
  795.                         ShowHide( theWindow, false );
  796.                         if ( behindWindow == nil )
  797.                             toBeDeactivated = thePWindow;
  798.                         else
  799.                         {
  800.                             if ( behindWindow != frontDocWindow )
  801.                             {
  802.                                 if ( frontWKind == toolKind )
  803.                                 {
  804.                                     HiliteTools( false );
  805.                                     SelectWindow(( WindowPtr )behindWindow );
  806.                                     toBeDeactivated = thePWindow;
  807.                                 }
  808.                                 if ( frontDocWindow != nil )
  809.                                     BringForward( frontDocWindow,
  810.                                         backToolWindow, normalCalc );
  811.                             }
  812.                             else
  813.                             {
  814.                                 if ( frontWKind == toolKind )
  815.                                 {
  816.                                     HiliteWindow( frontDocWindow, true );
  817.                                     toBeActivated   = frontDocWindow;
  818.                                     toBeDeactivated = thePWindow;
  819.                                 }
  820.                             }
  821.                         }
  822.                         break;
  823.             }
  824.         }
  825.         else
  826.         {
  827.                 /* The window is a modal dialog window. */
  828.  
  829.             switch( thePosition )
  830.             {
  831.                 case alone:
  832.                 case beforeSystem:
  833.                 case beforeDialog:
  834.                         HideWindow( theWindow );
  835.                         break;
  836.  
  837.                 case beforeTool:
  838.                 case beforeDocument:
  839.                         ShowHide( theWindow, false );
  840.                         HiliteTools( true );
  841.                         if ( frontDocWindow != nil )
  842.                         {
  843.                             toBeDeactivated = thePWindow;
  844.                             toBeActivated   = frontDocWindow;
  845.                             HiliteWindow(( WindowPtr )frontDocWindow, true );
  846.                         }
  847.                         break;
  848.             }
  849.         }
  850.     }
  851. }
  852.  
  853. /* End of THideWindow */
  854.  
  855.  
  856. /*
  857.  *    T S H O W W I N D O W
  858.  *
  859.  *    TShowWindow is a replacement for the standard ShowWindow function in
  860.  *    the toolbox.  Like ShowWindow,  TShowWindow makes the window visible
  861.  *    if it's not already visible (otherwise it has no effect).   It  also
  862.  *    makes very sure that the window will appear in an  allowed  position
  863.  *    for that window after it's been made visible.
  864.  *
  865.  *    TShowWindow calls GetWPosition to find out the exact position of the
  866.  *    window with respect to other windows on the desktop.   It then takes
  867.  *    specific action for each type of position, such as moving windows to
  868.  *    an allowed location first, or highlighting windows manually, posting
  869.  *    activate events and updating the global variables  front-  and back-
  870.  *    ToolWindow and frontDocWindow.
  871.  *
  872.  *    Parameters:
  873.  *
  874.  *      IN:
  875.  *
  876.  *        WindowPtr    theWindow;            window to be shown
  877.  *
  878.  *    Local variables:
  879.  *
  880.  *        WindowPeek    thePWindow,            WindowPeek version of theWindow
  881.  *                    theFrontWindow;        frontmost visible window
  882.  *        INTEGER        theWKind,            theWindow's windowKind
  883.  *                    frontWKind,            windowKind of theFrontWindow
  884.  *                    thePosition,        the window's relative position
  885.  *                    GetWPosition();        determines window's position
  886.  *        Boolean        toolsExist;            true if tools are visible
  887.  *
  888.  *    Used functions:
  889.  *
  890.  *        WindowPeek    PrevVisWindow();    window in front of given window
  891.  *        Boolean        BringToolsForward();brings all tools forward
  892.  *        void        BringForward(),        brings a window forward behind
  893.  *                                        another
  894.  *                    HiliteTools();        (Un)highlights all the tools
  895.  *
  896.  *    Global variables:
  897.  *
  898.  *        WindowPeek    frontToolWindow,    frontmost tool window
  899.  *                    backToolWindow,        backmost tool window
  900.  *                    frontDocWindow,        frontmost document window
  901.  *                    toBeActivated,        window that needs activating
  902.  *                    toBeDeactivated;    window that needs deactivating
  903.  *
  904.  *    Constants:
  905.  *
  906.  *        INTEGER        systemKind,            windowKind for DA windows
  907.  *                    toolKind,            windowKind for tool windows
  908.  *                    alone,                no other windows visible
  909.  *                    beforeDialog,        it is before the frontmost window,
  910.  *                                        which is a dialog window
  911.  *                    beforeSystem,        it is before the frontmost window,
  912.  *                                        which is a system window
  913.  *                    beforeTool,            it is before the frontmost window,
  914.  *                                        which is a tool window
  915.  *                    beforeDocument,        it is before the frontmost window,
  916.  *                                        which is a document window
  917.  *                    behindFrontSystem,    it is behind the frontmost window,
  918.  *                                        which is a system window
  919.  *                    betweenTools,        it is among the tool windows
  920.  *                    behindTools,        it is behind all the tool windows
  921.  *                                        but before any document windows
  922.  *                    behindSystem,        it is behind all the tool windows
  923.  *                                        and behind a system window
  924.  *                    betweenDocuments;    it is behind the first document
  925.  *                                        window
  926.  */
  927.  
  928. void
  929. TShowWindow( theWindow )
  930.     WindowPtr    theWindow;
  931. {
  932.     WindowPeek    thePWindow,
  933.                 theFrontWindow,
  934.                 behind,
  935.                 PrevVisWindow();
  936.     INTEGER        theWKind,
  937.                 frontWKind,
  938.                 thePosition,
  939.                 GetWPosition();
  940.     Boolean        toolsExist,
  941.                 BringToolsForward();
  942.     void        BringForward(),
  943.                 HiliteTools();
  944.  
  945.     if ((( WindowPeek )theWindow )->visible == false )
  946.     {
  947.                         /* The window is still invisible. */
  948.  
  949.         thePWindow       = ( WindowPeek )theWindow;
  950.         theFrontWindow = ( WindowPeek )FrontWindow();
  951.         theWKind       = TGetWKind( theWindow );
  952.         thePosition    = GetWPosition( thePWindow, &frontWKind );
  953.  
  954.         if ( theWKind == toolKind )
  955.         {
  956.                 /* The window is a tool window.  Assume it needs
  957.                    to appear highlighted (correct this later). */
  958.  
  959.             thePWindow->hilited = true;
  960.  
  961.             switch( thePosition )
  962.             {
  963.                 case beforeSystem:
  964.                         ShowWindow( theWindow );
  965.                         ( void )BringToolsForward( thePWindow );
  966.                         if ( frontDocWindow != nil )
  967.                         {
  968.                             frontDocWindow->hilited = true;
  969.                             BringForward( frontDocWindow,
  970.                                 backToolWindow, normalCalc );
  971.                             toBeActivated = frontDocWindow;
  972.                         }
  973.                         frontToolWindow = thePWindow;
  974.                         break;
  975.  
  976.                 case behindFrontSystem:
  977.                         thePWindow->hilited = false;
  978.                         
  979.                 case alone:
  980.                 case beforeDocument:
  981.                         if ( backToolWindow == nil )
  982.                              backToolWindow =  thePWindow;
  983.  
  984.                 case beforeTool:
  985.                         ShowHide( theWindow, true );
  986.                         frontToolWindow = thePWindow;
  987.                         break;
  988.  
  989.                 case behindTools:
  990.                         backToolWindow = thePWindow;
  991.  
  992.                 case betweenTools:
  993.                         if ( frontWKind == systemKind )
  994.                             thePWindow->hilited = false;
  995.                         ShowHide( theWindow, true );
  996.                         break;
  997.  
  998.                 case behindSystem:
  999.                         SendBehind( theWindow,
  1000.                                     ( WindowPtr )backToolWindow );
  1001.                         if ( frontWKind == systemKind )
  1002.                             thePWindow->hilited = true;
  1003.                         ShowHide( theWindow, true );
  1004.                         backToolWindow  = thePWindow;
  1005.                         break;
  1006.  
  1007.                 case betweenDocuments:
  1008.                         if ( backToolWindow != nil )
  1009.                             behind = backToolWindow;
  1010.                         else
  1011.                         {
  1012.                             behind = PrevVisWindow( frontDocWindow );
  1013.                             frontToolWindow = thePWindow;
  1014.                         }
  1015.                         if ( behind == nil )
  1016.                             BringToFront( theWindow );
  1017.                         else
  1018.                         {
  1019.                             SendBehind( theWindow, behind );
  1020.                             if ( frontWKind == systemKind )
  1021.                                 thePWindow->hilited = false;
  1022.                         }
  1023.                         ShowHide( theWindow, true );
  1024.                         backToolWindow = thePWindow;
  1025.                         break;
  1026.             }
  1027.         }
  1028.         else if ( theWKind == userKind )
  1029.         {
  1030.                 /* The window is a document window. */
  1031.  
  1032.             switch( thePosition )
  1033.             {
  1034.                 case beforeSystem:
  1035.                         toolsExist = BringToolsForward(
  1036.                                         ( WindowPeek )inFront );
  1037.                         if ( toolsExist != false )
  1038.                             thePWindow->hilited = true;
  1039.  
  1040.                 case alone:
  1041.                         ShowWindow( theWindow );
  1042.                         toBeActivated  =
  1043.                         frontDocWindow = thePWindow;
  1044.                         break;
  1045.  
  1046.                 case beforeTool:
  1047.                         if ( frontDocWindow != nil )
  1048.                         {
  1049.                             HiliteWindow(( WindowPtr )frontDocWindow,
  1050.                                                             false );
  1051.                             toBeDeactivated = frontDocWindow;
  1052.                         }
  1053.                         SendBehind( theWindow, backToolWindow );
  1054.                         thePWindow->hilited = true;
  1055.                         ShowHide( theWindow, true );
  1056.                         toBeActivated  =
  1057.                         frontDocWindow = thePWindow;
  1058.                         break;
  1059.  
  1060.                 case beforeDocument:
  1061.  
  1062.                             /* The three steps HiliteWindow,
  1063.                                HiliteWindow and ShowHide could be
  1064.                                replaced with one call to ShowWindow,
  1065.                                but this gives a better visual effect.
  1066.                                (Try the difference.) */
  1067.  
  1068.                         HiliteWindow( frontDocWindow, false );
  1069.                         HiliteWindow( theWindow, true );
  1070.                         ShowHide( theWindow, true );
  1071.                         toBeDeactivated = frontDocWindow;
  1072.                         toBeActivated   =
  1073.                         frontDocWindow  = thePWindow;
  1074.                         break;
  1075.  
  1076.                 case behindFrontSystem:
  1077.                         if ( backToolWindow != nil )
  1078.                             SendBehind( theWindow,
  1079.                                         ( WindowPtr )backToolWindow );
  1080.                         ShowHide( theWindow, true );
  1081.                         frontDocWindow  = thePWindow;
  1082.                         break;
  1083.  
  1084.                 case betweenTools:
  1085.                         SendBehind( theWindow,
  1086.                                     ( WindowPtr )backToolWindow );
  1087.  
  1088.                 case behindTools:
  1089.                         if ( frontWKind == toolKind )
  1090.                         {
  1091.                             thePWindow->hilited = true;
  1092.                             toBeActivated = thePWindow;
  1093.                             if ( frontDocWindow != nil )
  1094.                             {
  1095.                                 HiliteWindow(( WindowPtr )frontDocWindow,
  1096.                                                                 false );
  1097.                                 toBeDeactivated = frontDocWindow;
  1098.                             }
  1099.                         }
  1100.                         ShowHide( theWindow, true );
  1101.                         frontDocWindow  = thePWindow;
  1102.                         break;
  1103.  
  1104.                 case behindSystem:
  1105.                         SendBehind( theWindow,
  1106.                                     ( WindowPtr )backToolWindow );
  1107.                         if ( frontWKind == toolKind )
  1108.                         {
  1109.                             thePWindow->hilited = true;
  1110.                             toBeActivated = thePWindow;
  1111.                         }
  1112.                         ShowHide( theWindow, true );
  1113.                         frontDocWindow  = thePWindow;
  1114.                         break;
  1115.  
  1116.                 case betweenDocuments:
  1117.                         ShowHide( theWindow, true );
  1118.                         break;
  1119.             }
  1120.         }
  1121.         else
  1122.         {
  1123.                 /* The window is a modal dialog window. */
  1124.  
  1125.             switch( thePosition )
  1126.             {
  1127.                 case alone:
  1128.                 case beforeSystem:
  1129.                 case beforeDialog:
  1130.                         ShowWindow( theWindow );
  1131.                         break;
  1132.  
  1133.                 case beforeTool:
  1134.                 case beforeDocument:
  1135.                         HiliteTools( false );
  1136.                         if ( frontDocWindow != nil )
  1137.                         {
  1138.                             toBeDeactivated = frontDocWindow;
  1139.                             HiliteWindow(( WindowPtr )frontDocWindow, false );
  1140.                         }
  1141.                         ShowHide( theWindow, true );
  1142.                         break;
  1143.             }
  1144.         }
  1145.     }
  1146. }
  1147.  
  1148. /* End of TShowWindow */
  1149.  
  1150.  
  1151. /*
  1152.  *    T F R O N T W I N D O W
  1153.  *
  1154.  *    TFrontWindow effectively replaces the Toolbox trap FrontWindow in an
  1155.  *    environment with tool windows.  This function is not only for deter-
  1156.  *    mining just the frontmost visible window,  but the caller  can  also
  1157.  *    specify what kind of window it wants in  the  wantedKind  parameter.
  1158.  *    If there is a desk accessory or modal dialog  on  top,  TFrontWindow
  1159.  *    will return a pointer to the desk accessory's or dialog's window.
  1160.  *
  1161.  *    Parameters:
  1162.  *
  1163.  *      IN:
  1164.  *
  1165.  *        INTEGER        wantedKind;            kind of window to look for
  1166.  *
  1167.  *      OUT:
  1168.  *
  1169.  *        WindowPtr    TFrontWindow();        frontmost document window or nil
  1170.  *
  1171.  *    Local variables and used functions:
  1172.  *
  1173.  *        WindowPtr    theWindow;            the frontmost window
  1174.  *        INTEGER        theWKind;            the front window's windowKind
  1175.  *
  1176.  *    Global variables and constants:
  1177.  *
  1178.  *        WindowPeek    frontDocWindow,        frontmost document window
  1179.  *                    frontToolWindow;    frontmost tool window
  1180.  *        INTEGER        systemKind,            windowKind value for DA windows
  1181.  *                    toolKind,            windowKind value for tool windows
  1182.  *                    anyKind;            windowKind "wildcard"
  1183.  */
  1184.  
  1185. WindowPtr
  1186. TFrontWindow( wantedKind )
  1187.     INTEGER        wantedKind;
  1188. {
  1189.     WindowPtr    theWindow;
  1190.     INTEGER        theWKind;
  1191.  
  1192.     theWindow = FrontWindow();
  1193.     theWKind  = TGetWKind( theWindow );
  1194.  
  1195.     if ( theWKind == systemKind  ||
  1196.          theWKind == dialogKind )
  1197.         return( theWindow );
  1198.     else
  1199.         switch ( wantedKind )
  1200.         {
  1201.             case toolKind:
  1202.                     return(( WindowPtr )frontToolWindow );
  1203.                     break;
  1204.  
  1205.             case userKind:
  1206.                     return(( WindowPtr )frontDocWindow );
  1207.                     break;
  1208.  
  1209.             case anyKind:
  1210.                     return( theWindow );
  1211.                     break;
  1212.         }
  1213. }
  1214.  
  1215. /* End of TFrontWindow */
  1216.  
  1217.  
  1218. /*
  1219.  *    T D R A G W I N D O W
  1220.  *
  1221.  *    TDragWindow is  the  replacement for the Toolbox routine DragWindow.
  1222.  *    There are three things that DrawWindow does  which  are  replaced in
  1223.  *    TDragWindow: if the window is not in front it needs to be brought to
  1224.  *    the front (if the command key is not being held down).  This is done
  1225.  *    with a call to TSelectWindow.
  1226.  *
  1227.  *    The second thing is the dragging itself.  We use DragGrayRgn to draw
  1228.  *    a gray outline of the window (its strucRgn) around, _below_ any tool
  1229.  *    windows  and  other document windows that may be lying on top of it.
  1230.  *    This is accomplished by setting the  clipRgn of the  Window  Manager
  1231.  *    port (the port we're drawing in) "to be the desktop intersected with
  1232.  *    the current clipRgn,  minus the structure regions of all the windows
  1233.  *    in front of the given window".   This is  exactly what the low-level
  1234.  *    QuickDraw routine ClipAbove does.
  1235.  *
  1236.  *    The third and last step is to examine the result of DragGrayRgn, and
  1237.  *    to move the window accordingly. Watch the frequent changing of coor-
  1238.  *    dinates from global to local and vice versa!
  1239.  *
  1240.  *    Parameters:
  1241.  *
  1242.  *      IN:
  1243.  *
  1244.  *        WindowPtr    theWindow;        pointer to the window to be dragged
  1245.  *        EventRecord    *theEvent;        pointer to event that caused this
  1246.  *                                    call to TDragWindow
  1247.  *
  1248.  *    Local variables and used functions:
  1249.  *
  1250.  *        GrafPtr        savePort,        for saving the current grafport
  1251.  *                    wPort;            for holding the Window Manager port
  1252.  *        Rect        limitRect,        parameter for DragGrayRgn
  1253.  *                    slopRect;        parameter for DragGrayRgn
  1254.  *        RgnHandle    desktopRgn;        region for holding the desktop region
  1255.  *        LONGINT        result;            value DragGrayRgn returns
  1256.  *        INTEGER        hDrag,            horizontal displacement after dragging
  1257.  *                    vDrag;            vertical displacement after dragging
  1258.  *        Point        thePoint;        for calculating new position
  1259.  *
  1260.  *    Global constants and variables:
  1261.  *
  1262.  *        WindowPeek    frontDocWindow,    frontmost document window
  1263.  *        RgnHandle    GrayRgn,        low memory global holding desktop region
  1264.  *                    firstRgn,        for saving the Window Manager's clipRgn
  1265.  *                    secondRgn;        region that holds the drag outline
  1266.  */
  1267.  
  1268. void
  1269. TDragWindow( theWindow, theEvent, boundsRect )
  1270.     WindowPtr    theWindow;
  1271.     EventRecord    *theEvent;
  1272.     Rect        *boundsRect;
  1273. {
  1274.     GrafPtr        savePort,
  1275.                 wPort;
  1276.     Rect        limitRect,
  1277.                 slopRect;
  1278.     RgnHandle    desktopRgn;
  1279.     LONGINT        result;
  1280.     INTEGER        hDrag,
  1281.                 vDrag;
  1282.     Point        thePoint;
  1283.  
  1284.     if (( theEvent->modifiers & cmdKey ) == false )
  1285.     {
  1286.             /* If the command key is not being held down, call
  1287.                TSelectWindow to bring the window to the front.
  1288.                (TSelectWindow will determine if this is really
  1289.                necessary.)  Then make sure the mouse is still
  1290.                down before we start dragging. */
  1291.  
  1292.         TSelectWindow( theWindow );
  1293.         if ( StillDown() == false )
  1294.             return;
  1295.     }
  1296.         /* Save the current port and set it to the Window
  1297.            Manager port, since we're going to draw the
  1298.            drag outline in this port. */
  1299.  
  1300.     GetPort    ( &savePort );
  1301.     GetWMgrPort( &wPort );
  1302.     SetPort    (  wPort );
  1303.  
  1304.         /* Get a handle to the current desktop region.
  1305.            There is a routine for this on newer machines,
  1306.            but the old 64K ROM Mac and Mac XL will still
  1307.            have to get it from the low memory global GrayRgn. */
  1308.  
  1309. /*    if ( theWorld.machineType == envMac  ||
  1310.          theWorld.machineType == envXL    )    */
  1311.         desktopRgn = GrayRgn;
  1312. /*    else
  1313.         desktopRgn = GetGrayRgn();    */
  1314.  
  1315.         /* Set the clipping region to the current desktop
  1316.            region, intersected with all the windows above
  1317.            theWindow. */
  1318.  
  1319.     GetClip  ( firstRgn );
  1320.     SetClip  ( desktopRgn );
  1321.     ClipAbove(( WindowPeek )theWindow );
  1322.  
  1323.         /* Finally call DragGrayRgn to drag the outline
  1324.            of the window. */
  1325.  
  1326.     CopyRgn((( WindowPeek )theWindow )->strucRgn, secondRgn );
  1327.     SetPt  ( &thePoint, theEvent->where.h, theEvent->where.v );
  1328.     GlobalToLocal( &thePoint );
  1329.     result = DragGrayRgn( secondRgn, &thePoint, boundsRect,
  1330.                 boundsRect, noConstraint, ( ProcPtr )nil );
  1331.  
  1332.         /* Restore the Window Manager port's clipRgn. */
  1333.  
  1334.     SetClip( firstRgn );
  1335.  
  1336.         /* Check if the user actually moved the window.
  1337.            If so, call MoveWindow to move the window to
  1338.            its new location. */
  1339.  
  1340.     vDrag = HiWord( result );
  1341.     hDrag = LoWord( result );
  1342.     if ( !( vDrag == noDrag && hDrag == noDrag ))
  1343.     {
  1344.         SetPort( theWindow );
  1345.         SetPt  ( &thePoint, theWindow->portRect.left,
  1346.                             theWindow->portRect.top );
  1347.         LocalToGlobal( &thePoint );
  1348.         MoveWindow( theWindow, thePoint.h + hDrag,
  1349.                                thePoint.v + vDrag, false );
  1350.     }
  1351.  
  1352.         /* Restore the original grafport, and clear out
  1353.            the region handles. */
  1354.  
  1355.     SetPort( savePort );
  1356.     SetEmptyRgn( firstRgn );
  1357.     SetEmptyRgn( secondRgn );
  1358. }
  1359.  
  1360. /* End of TDragWindow */
  1361.  
  1362.  
  1363. /*
  1364.  *    T G E T N E X T E V E N T
  1365.  *
  1366.  *    TGetNextEvent is a replacement for the Toolbox routine GetNextEvent.
  1367.  *    It  still  calls  GetNextEvent,  but filters the activate events and
  1368.  *    sometimes  inserts activate events of its own.   This is because the
  1369.  *    movement of document  windows behind the tool windows goes unnoticed
  1370.  *    by the Window Manager, and no activate events are posted for them.
  1371.  *
  1372.  *    If there is a true activate event in the queue, it is because either
  1373.  *    a window was moved completely to the front,  or a desk accessory was
  1374.  *    opened or closed.   In the latter case, the frontmost window get the
  1375.  *    event,  but  it  is  really meant for the frontmost document window,
  1376.  *    which may be lying behind some tool windows.  TGetNextEvent modifies
  1377.  *    the event record to reflect this.
  1378.  *
  1379.  *    When the event  queue  doesn't hold any events of its own,  we check
  1380.  *    our own two globals toBeDeactivated and toBeActivated,in that order.
  1381.  *    If one of them points to a window,  we  return an activate event for
  1382.  *    that window.
  1383.  *
  1384.  *    Finally, if there are no activate events in the queue,but some other
  1385.  *    types,  or if the event queue is empty,  we simply call GetNextEvent
  1386.  *    and return the result.
  1387.  *
  1388.  *    Parameters:
  1389.  *
  1390.  *      IN:
  1391.  *
  1392.  *        INTEGER        eventMask;            types of events we want
  1393.  *
  1394.  *      OUT:
  1395.  *
  1396.  *        EventRecord    *theEvent;            event is returned here
  1397.  *
  1398.  *    Local variables and used functions:
  1399.  *
  1400.  *        Boolean        result,                result of GetNextEvent call
  1401.  *                    WindowExists();        true if passed window exists
  1402.  *        INTEGER        theWKind;            window's windowKind
  1403.  *        void        HiliteTools();        (Un)highlights all the tools
  1404.  *
  1405.  *    Global constants and variables:
  1406.  *
  1407.  *        WindowPeek    toBeActivated,        window that needs activating
  1408.  *                    toBeDeactivated,    window that needs deactivating
  1409.  *                    frontDocWindow;        frontmost document window
  1410.  *        INTEGER        deactivFlag;        modifiers for a deactivate event
  1411.  */
  1412.  
  1413. Boolean
  1414. TGetNextEvent( eventMask, theEvent )
  1415.     INTEGER        eventMask;
  1416.     EventRecord    *theEvent;
  1417. {
  1418.     Boolean        result,
  1419.                 WindowExists();
  1420.     INTEGER        theWKind;
  1421.     void        HiliteTools();
  1422.  
  1423.     if ( EventAvail( eventMask, theEvent ) != false  &&
  1424.          theEvent->what == activateEvt )
  1425.     {
  1426.             /* If there is an official activate event in the queue, get
  1427.                it  with  GetNextEvent,  and see what caused it.  If the
  1428.                corresponding  toBe... flag is the same as the activated
  1429.                or deactivated window,  it was a window that was brought
  1430.                to the front with SelectWindow or (Get)NewWindow.
  1431.  
  1432.                In that case the toBe... flag will already have been set
  1433.                up correctly, so don't do anything. If the (de)activated
  1434.                window is not equal to the right toBe... flag,  it means
  1435.                a  desk  accessory  was opened or closed.  In that case,
  1436.                pass the event on to the frontmost document window. */
  1437.  
  1438.         result = GetNextEvent( eventMask, theEvent );
  1439.         theWKind = TGetWKind(( WindowPtr )theEvent->message );
  1440.  
  1441.         if (( theEvent->modifiers & activeFlag ) == false )
  1442.         {
  1443.             if ( theEvent->message != ( LONGINT )toBeDeactivated )
  1444.             {
  1445.                 if ( toBeDeactivated != nil )
  1446.                     theEvent->message = ( LONGINT )toBeDeactivated;
  1447.                 else
  1448.                 {
  1449.                     if ( theWKind == userKind  ||
  1450.                          theWKind == toolKind  )
  1451.                     {
  1452.                         if ( theWKind == toolKind )
  1453.                             HiliteTools( false );
  1454.                         if ( frontDocWindow != nil )
  1455.                         {
  1456.                             HiliteWindow(( WindowPtr )frontDocWindow, false );
  1457.                             theEvent->message  = ( LONGINT )frontDocWindow;
  1458.                         }
  1459.                         else
  1460.                             result = TGetNextEvent( eventMask, theEvent );
  1461.                     }
  1462.                 }
  1463.             }
  1464.             toBeDeactivated = nil;
  1465.         }
  1466.         else
  1467.         {
  1468.             if ( theEvent->message != ( LONGINT )toBeActivated )
  1469.             {
  1470.                 if ( toBeActivated != nil )
  1471.                     theEvent->message = ( LONGINT )toBeActivated;
  1472.                 else
  1473.                 {
  1474.                     if ( theWKind == userKind  ||
  1475.                          theWKind == toolKind  )
  1476.                     {
  1477.                         if ( theWKind == toolKind )
  1478.                             HiliteTools( true );
  1479.                         if ( frontDocWindow != nil )
  1480.                         {
  1481.                             HiliteWindow(( WindowPtr )frontDocWindow, true );
  1482.                             theEvent->message  = ( LONGINT )frontDocWindow;
  1483.                         }
  1484.                         else
  1485.                             result = TGetNextEvent( eventMask, theEvent );
  1486.                     }
  1487.                 }
  1488.             }
  1489.             toBeActivated = nil;
  1490.         }
  1491.     }
  1492.     else
  1493.     {
  1494.             /* If there is no official activate event, but another type
  1495.                of event, or perhaps no event at all, first check to see
  1496.                if one of our toBe... variables is set, meaning that one
  1497.                of our windows needs activating or deactivating.  If so,
  1498.                fill in the caller's  event  record with the information
  1499.                for the (de)activate event. If none of our windows needs
  1500.                activating or deactivating,  just  call  GetNextEvent to
  1501.                get a pending event or a null event for the caller. */
  1502.  
  1503.         if ( toBeDeactivated != nil                    &&
  1504.              ( eventMask & activMask ) != false )
  1505.         {
  1506.             if ( WindowExists( toBeDeactivated ) != false )
  1507.             {
  1508.                     /* IMPORTANT: check if the window we are  about  to
  1509.                        deactivate still exists. This won't be a problem
  1510.                        if the window was removed by the TCloseWindow or
  1511.                        TDisposeWindow function  (since these  functions
  1512.                        remove the deactivate event themselves).  It  is
  1513.                        necessary if the window belonged to a dialog box
  1514.                        and was removed by CloseDialog or  DisposDialog.
  1515.                        Of course they don't clear toBeDeactivated... */
  1516.  
  1517.                 theEvent->what      = activateEvt;
  1518.                 theEvent->message   = ( LONGINT )toBeDeactivated;
  1519.                 theEvent->modifiers = deactivFlag;
  1520.                 toBeDeactivated     = nil;
  1521.                 result = true;
  1522.             }
  1523.             else
  1524.             {
  1525.                     /* The deactivate event was no longer valid,so call
  1526.                        TGetNextEvent again to get a fresh  event.   And
  1527.                        clear the bogus event of course. */
  1528.  
  1529.                 toBeDeactivated        = nil;
  1530.                 result = TGetNextEvent( eventMask, theEvent );
  1531.             }
  1532.         }
  1533.         else if ( toBeActivated != nil                &&
  1534.                   ( eventMask & activMask ) != false )
  1535.         {
  1536.             theEvent->what      = activateEvt;
  1537.             theEvent->message   = ( LONGINT )toBeActivated;
  1538.             theEvent->modifiers    = activeFlag;
  1539.             toBeActivated       = nil;
  1540.             result = true;
  1541.         }
  1542.         else
  1543.         {
  1544.             result = GetNextEvent( eventMask, theEvent );
  1545.         }
  1546.     }
  1547.         /* Return the result value to indicate if we have an event. */
  1548.  
  1549.     return( result );
  1550. }
  1551.  
  1552. /* End of TGetNextEvent */
  1553.  
  1554.  
  1555. /*
  1556.  *    W I N D O W E X I S T S
  1557.  *
  1558.  *    WindowExists determines if the given window is an  existing  window.
  1559.  *    It traverses the window list and if the window is not found, returns
  1560.  *    false.  If the window is found, it returns true.
  1561.  *
  1562.  *    Parameters:
  1563.  *
  1564.  *      IN:
  1565.  *
  1566.  *        WindowPeek    thePWindow;            window to check for existance
  1567.  *
  1568.  *      OUT:
  1569.  *
  1570.  *        Boolean        WindowExists();        true if window exists
  1571.  *
  1572.  *    Local variables and used functions:
  1573.  *
  1574.  *        WindowPeek    loopWindow,            to traverse the window list
  1575.  *        Boolean        done;                true if window exists
  1576.  */
  1577.  
  1578. Boolean
  1579. WindowExists( thePWindow )
  1580.     WindowPeek    thePWindow;
  1581. {
  1582.     WindowPeek    loopWindow;
  1583.     Boolean        done;
  1584.  
  1585.     for ( done = false,
  1586.             loopWindow = WindowList;
  1587.           done == false  &&  loopWindow != nil;
  1588.           loopWindow = loopWindow->nextWindow )
  1589.     {
  1590.         if ( loopWindow == thePWindow )
  1591.             done = true;
  1592.     }
  1593.     return( done );
  1594. }
  1595.  
  1596. /* End of WindowExists */
  1597.  
  1598.  
  1599. /*
  1600.  *    G E T W P O S I T I O N
  1601.  *
  1602.  *    GetWPosition is a  utility  function to determine the exact position
  1603.  *    of a window with respect to the other windows in the window list. It
  1604.  *    returns a predefined constant describing this position,  and another
  1605.  *    constant describing the type of window that is currently frontmost.
  1606.  *
  1607.  *    GetWPosition starts at the beginning of the window list, and traver-
  1608.  *    ses it until it finds our window.  In the meantime,  it remembers in
  1609.  *    what state it is,  so  that when it finds the window,  it knows what
  1610.  *    kind of result code to return. There are 10 result codes, correspon-
  1611.  *    ding to the 10 different kinds of positions a window can have.
  1612.  *
  1613.  *    Parameters:
  1614.  *
  1615.  *      IN:
  1616.  *
  1617.  *        WindowPeek    thePWindow;            window to find position of
  1618.  *
  1619.  *      OUT:
  1620.  *
  1621.  *        INTEGER        *frontWKind;        kind of window currently in front
  1622.  *
  1623.  *      IN/OUT:
  1624.  *
  1625.  *        <none>
  1626.  *
  1627.  *    Local variables and used functions:
  1628.  *
  1629.  *        WindowPeek    theFrontWindow,        the frontmost window
  1630.  *                    newFrontWindow,        new front window after hide
  1631.  *                    loopWindow,            to traverse the window list
  1632.  *                    NextVisWindow();    returns next visible window
  1633.  *        Boolean        done;                signals end of while loop
  1634.  *        INTEGER        result,                result code describing position
  1635.  *                    loopKind;            kind of window during loop
  1636.  *
  1637.  *    Global variables:
  1638.  *
  1639.  *        WindowPeek    frontToolWindow,    frontmost tool window
  1640.  *                    backToolWindow,        backmost tool window
  1641.  *                    frontDocWindow;        frontmost document window
  1642.  *
  1643.  *    Constants:
  1644.  *
  1645.  *        INTEGER        systemKind,            windowKind for DA windows
  1646.  *                    toolKind,            windowKind for tool windows
  1647.  *                    anyKind,            windowKind "wildcard"
  1648.  *                    alone,                no other windows visible
  1649.  *                    beforeDialog,        it is before the frontmost window,
  1650.  *                                        which is a dialog window
  1651.  *                    beforeSystem,        it is before the frontmost window,
  1652.  *                                        which is a system window
  1653.  *                    beforeTool,            it is before the frontmost window,
  1654.  *                                        which is a tool window
  1655.  *                    beforeDocument,        it is before the frontmost window,
  1656.  *                                        which is a document window
  1657.  *                    behindFrontSystem,    it is behind the frontmost window,
  1658.  *                                        which is a system window
  1659.  *                    betweenTools,        it is among the tool windows
  1660.  *                    behindTools,        it is behind all the tool windows
  1661.  *                    behindSystem,        it is behind all the tool windows,
  1662.  *                                        and behind a system window, but
  1663.  *                                        before any document windows
  1664.  *                    betweenDocuments;    it is behind the first document
  1665.  *                                        window
  1666.  */
  1667.  
  1668. static INTEGER
  1669. GetWPosition( thePWindow, frontWKind )
  1670.     WindowPeek    thePWindow;
  1671.     INTEGER        *frontWKind;
  1672. {
  1673.     WindowPeek    theFrontWindow,
  1674.                 newFrontWindow,
  1675.                 loopWindow,
  1676.                 NextVisWindow();
  1677.     Boolean        done;
  1678.     INTEGER        result,
  1679.                 loopWKind;
  1680.  
  1681.         /* Initialize several variables. */
  1682.  
  1683.     theFrontWindow = ( WindowPeek )FrontWindow();
  1684.  
  1685.         /* If our window is visible and the frontmost,
  1686.            examine the visible window behind ours. */
  1687.  
  1688.     if ( thePWindow->visible != false    &&
  1689.          theFrontWindow == thePWindow    )
  1690.         newFrontWindow = NextVisWindow( anyKind, theFrontWindow );
  1691.     else
  1692.         newFrontWindow = theFrontWindow;
  1693.  
  1694.         /* If our window is visible, and there are no
  1695.            windows following it, or if our window is
  1696.            invisible and there are no visible windows
  1697.            at all, return right away. */
  1698.  
  1699.     if ( newFrontWindow == nil )
  1700.         return( alone );
  1701.     *frontWKind = TGetWKind(( WindowPtr )newFrontWindow );
  1702.  
  1703.     if ( thePWindow->visible != false    &&
  1704.          theFrontWindow == thePWindow    ||
  1705.          theFrontWindow == NextVisWindow( anyKind, thePWindow ))
  1706.     {
  1707.             /* Our window is visible and the frontmost,
  1708.                or it's invisible and lying in front of
  1709.                the frontmost visible window. */
  1710.  
  1711.         if ( *frontWKind == systemKind )
  1712.             result      = beforeSystem;
  1713.         else if ( *frontWKind == dialogKind )
  1714.             result        = beforeDialog;
  1715.         else if ( *frontWKind == toolKind )
  1716.             result      = beforeTool;
  1717.         else
  1718.             result      = beforeDocument;
  1719.     }
  1720.     else
  1721.     {
  1722.             /* Our window is not completely in front, but
  1723.                behind the frontmost visible window. Traverse
  1724.                the window list, marking every transition to
  1725.                another category of windows by setting the
  1726.                result code to the current state.  If our
  1727.                window is invisible, we stop when we find it.
  1728.                If our window is visible, we stop when we
  1729.                reach the window in front of it. */
  1730.  
  1731.         if (thePWindow->visible != false )
  1732.             thePWindow = PrevVisWindow( thePWindow );
  1733.  
  1734.         for ( done = false,
  1735.                 loopWindow = theFrontWindow;
  1736.               done == false;
  1737.               loopWindow = loopWindow->nextWindow )
  1738.         {
  1739.             loopWKind = TGetWKind(( WindowPtr )loopWindow );
  1740.             if ( loopWindow == theFrontWindow  &&
  1741.                  loopWKind  == systemKind       )
  1742.                 result = behindFrontSystem;
  1743.             else if ( loopWindow     == frontToolWindow     &&
  1744.                       backToolWindow != frontToolWindow  )
  1745.                 result = betweenTools;
  1746.             else if ( loopWindow == backToolWindow )
  1747.                 result = behindTools;
  1748.             else if ( loopWKind == systemKind        &&
  1749.                       loopWindow->visible != false    &&
  1750.                       result == behindTools )
  1751.                 result = behindSystem;
  1752.             else if ( loopWindow == frontDocWindow )
  1753.                 result = betweenDocuments;
  1754.  
  1755.             if ( loopWindow == thePWindow )
  1756.                 done = true;
  1757.         }
  1758.             /* Finish by returning the result code. */
  1759.  
  1760.         return( result );
  1761.     }
  1762. }
  1763.  
  1764. /* End of GetWPosition */
  1765.  
  1766.  
  1767. /*
  1768.  *    T G E T W K I N D
  1769.  *
  1770.  *    TGetWKind is a utility function that returns the class of the window
  1771.  *    that is passed to it,  based on the WindowRecord's windowKind field.
  1772.  *    TGetWKind returns the constant systemKind  if the window is  a  desk
  1773.  *    accessory, the constant dialogKind if it's a modal dialog  or  alert
  1774.  *    window, the constant toolKind if it's a tool window, and finally the
  1775.  *    constant userKind for a document window or a modeless dialog window.
  1776.  *
  1777.  *    TGetWKind simply returns the value of windowKind in most cases (when
  1778.  *    the window is a DA, it always chooses systemKind,  and  when it is a
  1779.  *    standard window it always chooses userKind,  no matter what the real
  1780.  *    value of windowKind may be). It also returns userKind for a modeless
  1781.  *    dialog window.
  1782.  *
  1783.  *    Parameters:
  1784.  *
  1785.  *      IN:
  1786.  *
  1787.  *        WindowPtr    theWindow;            window to find position of
  1788.  *
  1789.  *      OUT:
  1790.  *
  1791.  *        <none>
  1792.  *
  1793.  *      IN/OUT:
  1794.  *
  1795.  *        <none>
  1796.  *
  1797.  *    Local variables:
  1798.  *
  1799.  *        INTEGER        theWKind,            windowKind of theWindow
  1800.  *                    windowID;            windowID of theWindow
  1801.  *        Handle        defProc;            handle to theWindow's defProc
  1802.  *
  1803.  *    Global variables:
  1804.  *
  1805.  *        SysEnvRec    theWorld;            SysEnvirons record
  1806.  *
  1807.  *    Constants:
  1808.  *
  1809.  *        INTEGER        systemKind,            windowKind for DA windows
  1810.  *                    toolKind;            windowKind for tool windows
  1811.  */
  1812.  
  1813. INTEGER
  1814. TGetWKind( theWindow )
  1815.     WindowPtr    theWindow;
  1816. {
  1817.     INTEGER        theWKind,
  1818.                 varCode,
  1819.                 windowID;
  1820.     WDEFHandle    defProc;
  1821.  
  1822.     if ( theWindow != nil )
  1823.     {
  1824.         theWKind = (( WindowPeek )theWindow )->windowKind;
  1825.  
  1826.         if ( theWKind <= systemKind )
  1827.             theWKind = systemKind;
  1828.         else if ( theWKind == dialogKind )
  1829.         {
  1830.             defProc =
  1831.                 ( WDEFHandle )(( WindowPeek )theWindow )->windowDefProc;
  1832.  
  1833. /*            if ( theWorld.machineType == envMac  ||
  1834.                  theWorld.machineType == envXL    )        */
  1835.                 varCode  = ( LONGINT )defProc >> 24 && 0x0000000F;
  1836. /*            else
  1837.                 varCode = GetWVariant( theWindow );        */
  1838.  
  1839.             if (   defProc != nil    &&
  1840.                   *defProc != nil     &&
  1841.                 ( *defProc )->type == 'WDEF' )
  1842.                 windowID = ( *defProc )->ID * 16 + varCode;
  1843.             else
  1844.                 windowID = dBoxProc;
  1845.  
  1846.             if ( windowID == documentProc    ||
  1847.                  windowID == noGrowDocProc    ||
  1848.                  windowID == zoomDocProc       )
  1849.                 theWKind = userKind;
  1850.         }
  1851.         else if ( theWKind == toolKind )
  1852.             /* nothing */ ;
  1853.         else if ( theWKind >= userKind )
  1854.             theWKind = userKind;
  1855.     }
  1856.     return( theWKind );
  1857. }
  1858.  
  1859. /* End of TGetWKind */
  1860.  
  1861.  
  1862. /*
  1863.  *    B R I N G T O O L S F O R W A R D
  1864.  *
  1865.  *    BringToolsForward is used to move a range of visible tool windows further
  1866.  *    to the front. If the behindWindow parameter is inFront, BringToolsForward
  1867.  *    will use SelectWindow to bring the first visible tool window to the front,
  1868.  *    effectively  deactivating  a desk accessory that may be lying on top.  It
  1869.  *    will then traverse the rest of the visible  tool  windows  and bring them
  1870.  *    all behind that first selected one. If the behindWindow  parameter is not
  1871.  *    equal to inFront,  BringToolsForward  will just traverse the visible tool
  1872.  *    windows following behindWindow and move them forward to the new  position
  1873.  *    (just behind behindWindow), "across" any desk accessories.  Note that the
  1874.  *    BringForward function is passed the postponeCalc parameter. This tells it
  1875.  *    not to call the time-consuming CalcVisBehind function during  each  move.
  1876.  *    Instead, BringToolsForward saves up all the regions for one call to Calc-
  1877.  *    VisBehind, after all the tools are moved forward.
  1878.  *
  1879.  *    BringToolsForward returns true if it really encountered visible tool win-
  1880.  *    dows and moved them  forward.   If there were no tool visible  windows at
  1881.  *    all, a result of false is returned.
  1882.  *
  1883.  *    Parameters:
  1884.  *
  1885.  *      IN:
  1886.  *
  1887.  *        WindowPeek    thePWindow;            move visible tool windows forward
  1888.  *                                        just behind this window, or to the
  1889.  *                                        front if it's equal to inFront
  1890.  *      OUT:
  1891.  *
  1892.  *        Boolean        BringToolsForward();true if tools were brought forward
  1893.  *                                        and the desk accessory deactivated
  1894.  *
  1895.  *    Local variables and used functions:
  1896.  *
  1897.  *        WindowPeek    NextVisWindow();    returns next visible window
  1898.  *                    toolWindow,            used for various purposes
  1899.  *                    loopWindow;            used for various purposes
  1900.  *        void        BringForward();        moves a window behind another
  1901.  *
  1902.  *    Global variables and constants:
  1903.  *
  1904.  *        INTEGER        toolKind;            windowKind value for tool windows
  1905.  *        WindowPtr    inFront;            indicates we want window in front
  1906.  *        WindowPeek    toBeActivated,         window that needs activating
  1907.  *                    frontToolWindow,    frontmost tool window
  1908.  *                    backToolWindow;        backmost tool window
  1909.  *        RgnHandle    secondRgn;            clobberedRgn for CalcVisBehind
  1910.  *        Boolean        postponeCalc;        tells BringForward not to call
  1911.  *                                        CalcVisBehind yet
  1912.  */
  1913.  
  1914. static Boolean
  1915. BringToolsForward( thePWindow )
  1916.     WindowPeek    thePWindow;
  1917. {
  1918.     WindowPeek    NextVisWindow(),
  1919.                 toolWindow,
  1920.                 loopWindow;
  1921.     void        BringForward();
  1922.  
  1923.     if ( thePWindow == ( WindowPeek )inFront )
  1924.     {
  1925.             /* Find the frontmost tool window behind the DA(s). */
  1926.  
  1927.         toolWindow = NextVisWindow( toolKind, ( WindowPeek )FrontWindow() );
  1928.  
  1929.             /* If it's not nil, we use SelectWindow to bring it in
  1930.                front (and to deactivate the desk accessory).  Back-
  1931.                ToolWindow and frontToolWindow are initialized, and
  1932.                loopWindow is prepared for traversing the remaining
  1933.                visible tool windows. */
  1934.  
  1935.         if ( toolWindow != nil )
  1936.         {
  1937.             loopWindow      = toolWindow->nextWindow;
  1938.             SelectWindow(( WindowPtr )toolWindow );
  1939.             frontToolWindow =
  1940.             backToolWindow  = toolWindow;
  1941.         }
  1942.             /* If it's nil, it means there are no visible tool
  1943.                windows.  Return with false to indicate that there
  1944.                are no tool windows visible and that the topmost DA
  1945.                has not been deactivated yet. */
  1946.         else
  1947.         {
  1948.             return( false );
  1949.         }
  1950.     }
  1951.         /* Set up loopWindow and backToolWindow to start moving
  1952.            the visible tool windows behind thePWindow forward. */
  1953.     else
  1954.     {
  1955.         loopWindow     = thePWindow->nextWindow;
  1956.         backToolWindow = thePWindow;
  1957.     }
  1958.  
  1959.         /* Traverse the rest of the visible tool windows,
  1960.            and move them just behind backToolWindow, across
  1961.            the DA(s).  Add each tool window's strucRgn to
  1962.            the region that will be used for one call to
  1963.            CalcVisBehind. */
  1964.  
  1965.     SetEmptyRgn( secondRgn );
  1966.     thePWindow = nil;
  1967.  
  1968.     while ( loopWindow != nil )
  1969.     {
  1970.         if ( loopWindow->windowKind == toolKind  &&
  1971.              loopWindow->visible    != false     )
  1972.         {
  1973.             toolWindow = loopWindow;
  1974.             toolWindow->hilited = true;
  1975.             BringForward( toolWindow, backToolWindow, postponeCalc );
  1976.             UnionRgn( secondRgn, toolWindow->strucRgn, secondRgn );
  1977.             backToolWindow = toolWindow;
  1978.             if ( thePWindow == nil )
  1979.                 thePWindow = toolWindow;
  1980.         }
  1981.         loopWindow = loopWindow->nextWindow;
  1982.     }
  1983.  
  1984.     CalcVisBehind( thePWindow, secondRgn );
  1985.     SetEmptyRgn( secondRgn );
  1986.  
  1987.         /* Return true to indicate that there are actually
  1988.            tool windows visible (and that all of those
  1989.            visible windows were moved). */
  1990.  
  1991.     return( true );
  1992. }
  1993.  
  1994. /* End of BringToolsForward */
  1995.  
  1996.  
  1997. /*
  1998.  *    N E X T V I S W I N D O W
  1999.  *
  2000.  *    NextVisWindow returns the next visible window of type wantedKind following
  2001.  *    thePWindow.  It traverses the window list,  skipping invisible windows and
  2002.  *    windows of the wrong type, until it finds this type of window.  If it does
  2003.  *    not find a next visible window, nil is returned.
  2004.  *
  2005.  *    It is allowed to pass the constant inFront as thePWindow;  searching  will
  2006.  *    then commence with the frontmost  visible window.  If  wantedKind is equal
  2007.  *    to the predefined constant anyKind, NextVisWindow returns the next visible
  2008.  *    window, no matter what kind.
  2009.  *
  2010.  *    Parameters:
  2011.  *
  2012.  *      IN:
  2013.  *
  2014.  *        INTEGER        wantedKind;            kind of window to look for
  2015.  *        WindowPeek    thePWindow;            window to start looking behind
  2016.  *
  2017.  *      OUT:
  2018.  *
  2019.  *        WindowPeek    NextVisWindow();    first visible wantedKind window
  2020.  *                                        behind thePWindow or nil
  2021.  *
  2022.  *    Local variables and used functions:
  2023.  *
  2024.  *        WindowPeek    loopWindow,            used for various purposes
  2025.  *                    wantedWindow;        window to look for; end of for loop
  2026.  *
  2027.  *    Constants:
  2028.  *
  2029.  *        INTEGER        anyKind;            windowKind "wildcard"
  2030.  *        WindowPtr    inFront;            indicates we want window in front
  2031.  */
  2032.  
  2033. static WindowPeek
  2034. NextVisWindow( wantedKind, thePWindow )
  2035.     INTEGER        wantedKind;
  2036.     WindowPeek    thePWindow;
  2037. {
  2038.     WindowPeek    loopWindow,
  2039.                 wantedWindow;
  2040.  
  2041.         /* If thePWindow is equal to the predefined constant
  2042.            inFront, set it to FrontWindow().  Check if this is
  2043.            possibly the window we're looking for.  If yes, return
  2044.            it.  If no, fall through to the loop below. */
  2045.  
  2046.     if ( thePWindow == ( WindowPeek )inFront )
  2047.     {
  2048.         thePWindow = ( WindowPeek )FrontWindow();
  2049.         if ( thePWindow == nil )
  2050.             return( thePWindow );
  2051.         else if ( wantedKind == anyKind        ||
  2052.                   wantedKind == TGetWKind(( WindowPtr )thePWindow ))
  2053.             return( thePWindow );
  2054.     }
  2055.  
  2056.         /* Traverse the window list, starting with the window
  2057.            following thePWindow, in search of the frontmost
  2058.            visible wantedKind type window. */
  2059.  
  2060.     for ( wantedWindow = nil,
  2061.             loopWindow = thePWindow->nextWindow;
  2062.           wantedWindow == nil  &&
  2063.             loopWindow != nil;
  2064.           loopWindow = loopWindow->nextWindow )
  2065.     {
  2066.         if ( loopWindow->visible != false )
  2067.             if ( wantedKind == anyKind        ||
  2068.                  wantedKind == TGetWKind(( WindowPtr )loopWindow ))
  2069.                 wantedWindow = loopWindow;
  2070.     }
  2071.  
  2072.     return( wantedWindow );
  2073. }
  2074.  
  2075. /* End of NextVisWindow */
  2076.  
  2077.  
  2078. /*
  2079.  *    P R E V V I S W I N D O W
  2080.  *
  2081.  *    PrevVisWindow returns the next visible window in front  of  thePWindow  in
  2082.  *    the window list.  It traverses the window list until it finds this window.
  2083.  *    If there is no such window, PrevVisWindow returns nil.
  2084.  *
  2085.  *    Parameters:
  2086.  *
  2087.  *      IN:
  2088.  *
  2089.  *        WindowPeek    thePWindow;            window to find previous visible for
  2090.  *
  2091.  *      OUT:
  2092.  *
  2093.  *        WindowPeek    PrevVisWindow();    first visible window in front of
  2094.  *                                        thePWindow, or nil if none
  2095.  *
  2096.  *    Local variables and used functions:
  2097.  *
  2098.  *        WindowPeek    loopWindow,            used for various purposes
  2099.  *                    prevWindow,            candidate for previous visible window
  2100.  *                    theFrontWindow,        frontmost visible window
  2101.  *                    NextVisWindow();    next visible window in window list
  2102.  *        Boolean        done;                signals end of while loop
  2103.  *
  2104.  *    Constants:
  2105.  *
  2106.  *        INTEGER        anyKind;            windowKind "wildcard"
  2107.  */
  2108.  
  2109. static WindowPeek
  2110. PrevVisWindow( thePWindow )
  2111.     WindowPeek    thePWindow;
  2112. {
  2113.     WindowPeek    loopWindow,
  2114.                 prevWindow,
  2115.                 theFrontWindow,
  2116.                 NextVisWindow();
  2117.     Boolean        done;
  2118.  
  2119.     theFrontWindow = ( WindowPeek )FrontWindow();
  2120.  
  2121.         /* If thePWindow is the frontmost visible or even
  2122.            frontmost invisible window, return nil. */
  2123.  
  2124.     if ( thePWindow  == theFrontWindow  ||
  2125.          theFrontWindow == NextVisWindow( anyKind, thePWindow ))
  2126.         return(( WindowPeek )nil );
  2127.  
  2128.         /* Traverse the window list, starting with the
  2129.            frontmost visible window, and see if one of
  2130.            the windows following it up to (and including)
  2131.            the next visible window is our window.  If not,
  2132.            move to the  next visible window. */
  2133.  
  2134.     prevWindow = theFrontWindow;
  2135.     loopWindow = prevWindow->nextWindow;
  2136.     done = false;
  2137.  
  2138.     while ( done == false )
  2139.     {
  2140.         if ( loopWindow == thePWindow )
  2141.             done = true;
  2142.         else
  2143.             if ( loopWindow->visible != false )
  2144.                 prevWindow = loopWindow;
  2145.             loopWindow = loopWindow->nextWindow;
  2146.     }
  2147.  
  2148.     return( prevWindow );
  2149. }
  2150.  
  2151. /* End of PrevVisWindow */
  2152.  
  2153.  
  2154. /*
  2155.  *    B R I N G F O R W A R D
  2156.  *
  2157.  *    BringForward is a special function to move a window further to the front.
  2158.  *    The move is accomplished by three calls to the Window Manager: SendBehind
  2159.  *    to move the window, PaintOne to paint the newly uncovered content region,
  2160.  *    and finally - if waitWithCalc is not true - CalcVisBehind to  recalculate
  2161.  *    the visRgns of all the windows behind our window. NOTE:  Inside Macintosh
  2162.  *    (page I-286) mentions that a call to  SendBehind in a case like this must
  2163.  *    be followed by calls to the routines PaintOne and CalcVis. However, Calc-
  2164.  *    Vis just isn't enough here: we need to recalculate the visRgns  of  _all_
  2165.  *    windows behind our window.
  2166.  *
  2167.  *    Parameters:
  2168.  *
  2169.  *      IN:
  2170.  *
  2171.  *        WindowPeek    thePWindow,            window that needs to be moved forward
  2172.  *                    behindWindow;        ... behind this window
  2173.  *        Boolean        waitWithCalc;        if true, dont call CalcVisBehind
  2174.  *
  2175.  *    Global variables:
  2176.  *
  2177.  *        RgnHandle    firstRgn;            uncovered region of window to redraw
  2178.  */
  2179.  
  2180. static void
  2181. BringForward( thePWindow, behindWindow, waitWithCalc )
  2182.     WindowPeek    thePWindow;
  2183.     WindowPeek    behindWindow;
  2184.     Boolean        waitWithCalc;
  2185. {
  2186.         /* The newly exposed part of the structure region of our window
  2187.            is calculated (remember that visRgn is in local coordinates). */
  2188.  
  2189.     CopyRgn  ( thePWindow->strucRgn, firstRgn );
  2190.     OffsetRgn( thePWindow->port.visRgn,
  2191.                 - thePWindow->port.portBits.bounds.left,
  2192.                 - thePWindow->port.portBits.bounds.top  );
  2193.     DiffRgn  ( firstRgn, thePWindow->port.visRgn, firstRgn );
  2194.     OffsetRgn( thePWindow->port.visRgn,
  2195.                    thePWindow->port.portBits.bounds.left,
  2196.                    thePWindow->port.portBits.bounds.top  );
  2197.  
  2198.         /* Move the window to its new position, paint the newly
  2199.            exposed part of of the window's contents white, and
  2200.            recalculate the lower windows' visRgns. */
  2201.  
  2202.     SendBehind(( WindowPtr )thePWindow, ( WindowPtr )behindWindow );
  2203.     PaintOne     ( thePWindow, firstRgn );
  2204.     if ( waitWithCalc == false )
  2205.         CalcVisBehind( thePWindow, thePWindow->strucRgn );
  2206.     SetEmptyRgn( firstRgn );
  2207. }
  2208.  
  2209. /* End of BringForward */
  2210.  
  2211.  
  2212. /*
  2213.  *    H I L I T E T O O L S
  2214.  *
  2215.  *    HiliteTools is a utility function that highlights or unhighlights all the
  2216.  *    tool windows that are visible.  Its main purpose is  to  unhighlight  the
  2217.  *    tools whenever a window that doesn't belong to the application is brought
  2218.  *    to the front,or to highlight the tools when such a window is removed from
  2219.  *    the frontmost position.  This can be a desk accessory  when  running  the
  2220.  *    standard Mac operating system, or can be any  application's  window  when
  2221.  *    running under MultiFinder.
  2222.  *
  2223.  *    Parameters:
  2224.  *
  2225.  *      IN:
  2226.  *
  2227.  *        Boolean            hilite;                true = hilite, false = unhilite
  2228.  *
  2229.  *    Local variables and used functions:
  2230.  *
  2231.  *        WindowPeek        loopWindow;            used to traverse windows
  2232.  *        Boolean            done;                signals end of while loop
  2233.  *
  2234.  *    Global variables:
  2235.  *
  2236.  *        WindowPeek        frontToolWindow,    frontmost tool window
  2237.  *                        backToolWindow;        backmost tool window
  2238.  */
  2239.  
  2240. static void
  2241. HiliteTools( hilite )
  2242.     Boolean        hilite;
  2243. {
  2244.     WindowPeek    loopWindow;
  2245.     Boolean        done;
  2246.  
  2247.     if ( frontToolWindow != nil )
  2248.     {
  2249.         for ( done = false,
  2250.                 loopWindow = frontToolWindow;
  2251.               done == false  &&  loopWindow != nil;
  2252.               loopWindow = loopWindow->nextWindow )
  2253.         {
  2254.             if ( TGetWKind(( WindowPtr )loopWindow ) == toolKind  &&
  2255.                  loopWindow->visible != false )
  2256.             {
  2257.                 HiliteWindow(( WindowPtr )loopWindow, hilite );
  2258.                 if ( loopWindow == backToolWindow )
  2259.                     done = true;
  2260.             }
  2261.         }
  2262.     }
  2263. }
  2264.  
  2265. /* End of HiliteTools */
  2266.